/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * leafget
 * Copyright (C) xinliGG 2008 <xinliGG@gmail.com>
 * 
 * leafget is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * leafget is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <gtk/gtk.h>
#include <glibmm/thread.h>
#include <gtkmm/dialog.h>
#include <gtkmm/stock.h>

#include <fstream>

#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#include "leafget.h"
#include "preferences.h"
#include "new.h"
#include "msg.h"
#include "util.h"
#include "mainwindow.h"

#include "../data/leafget_icons.xpm"
#include "../data/shamrock.xpm"

#define SIZE_X 800
#define SIZE_Y 600

#define LIST_TIMER 300
#define CMD_TIMER  150

#define TASK_PAUSED   -1
#define TASK_ENQUEUED -2

#define OPTION_NOT_ASKED -1
#define OPTION_RESUME     0
#define OPTION_REPLACE    1

//#define RUNNING_GROUP   0
//#define COMPLETED_GROUP 1
//#define TRASH_GROUP    2

#define CONFIG_FILE_NAME  "leafget_config"
#define HISTORY_FILE_NAME "leafget_history"
#define LOG_FILE_NAME     "leafget.log"

#ifdef VERSION
#define LEAFGET_VERSION "Version "VERSION
#else
#define LEAFGET_VERSION "0.0.1"
#endif /* VERSION */

#ifndef PACKAGE_BUGREPORT
#define PACKAGE_BUGREPORT "xinliGG@gmail.com"
#endif /* PACKAGE_BUGREPORT */


main_window::main_window ( char **argv )
	: update_list( false ),
	  threadCount ( 0 ),
	  mainBox (false, 0),
	  is_cmd( false ),
	  is_default( false ),
	  argv( argv )
{
		/* setting window properties */

	set_title( "Leafget" );
	set_default_size( SIZE_X, SIZE_Y );

//	gchar *logo_file = g_strdup_printf("%s/%s","../data","completed.png");
//	refPixbuf_winIcon =Gdk::Pixbuf::create_from_file (logo_file);
//	g_free (logo_file);
	refPixbuf_winIcon = Gdk::Pixbuf::create_from_xpm_data( leafget_icon );
	set_icon( refPixbuf_winIcon );

		/* setting variables */

	listGroup = RUNNING_GROUP;

	//设定home目录路径
	define_home();

	load_config();

		/* setting log */
	Util::set_logPath( homePath + LOG_FILE_NAME );
	Util::check_log();
	
	for( int i = 0; i < MAX_TASKS; i++ )
		thread[i] = NULL;

		/* adding widgets */
	
	add( mainBox );

		/* building */

	build_menu_bar();

	mainBox.pack_start( HPaned );
	HPaned.set_position( 160 );
	build_left_tree();
	HPaned.pack2( VPanedR, false, false );
	build_right_list ();
	load_history();
	
	statusBar.set_size_request( -1, 25 );
	build_status_bar();
	mainBox.pack_start( statusBar, Gtk::PACK_SHRINK, 0 );
	refStatusToggle->set_active();
	
	build_status_icon();

		/* cmd timer */
	cmd_connect = Glib::signal_timeout().connect( sigc::mem_fun( *this, &main_window::on_cmd_link ), CMD_TIMER );

		/* list timer */
	connect_list_timer();

		/* show widgets */
	show_all_children();
}

main_window::~main_window ( void )
{
	save_history();
	
	for ( int i = 0; i < MAX_TASKS; i++ )
	{
		if ( thread[i] && thread[i]->isRunning() )
			delete thread[i];
	}
}


	/* build functions */
		
void main_window::build_menu_bar   ( void )
{
		/* create actions for menus and toolbars */

	refActionGroup = Gtk::ActionGroup::create();
	
		/* file menu */

	refActionGroup->add( Gtk::Action::create( "FileMenu", "File" ) );
	refActionGroup->add( Gtk::Action::create( "FileQuit", Gtk::Stock::QUIT ),
		sigc::mem_fun( *this, &main_window::on_menu_file_quit ) );

		/* view menu */

	refActionGroup->add( Gtk::Action::create( "ViewMenu", "View" ) );	
	refStatusToggle = Gtk::ToggleAction::create( "ViewStatus", "Show Status" );
	refActionGroup->add( refStatusToggle,
		sigc::mem_fun( *this, &main_window::on_menu_view_status ) );
//	refActionGroup->add(Gtk::Action::create( "ViewPreferences", Gtk::Stock::PREFERENCES ), Gtk::AccelKey( "<control><alt>P" ),
//		sigc::mem_fun( *this, &main_window::on_menu_view_preferences ) );

		/* task menu */

	refActionGroup->add( Gtk::Action::create( "TaskMenu", "Task" ) );
	refActionGroup->add( Gtk::Action::create( "TaskNew", Gtk::Stock::NEW ), Gtk::AccelKey( "<control>N") ,
		sigc::mem_fun( *this, &main_window::on_menu_task_new ) );
	refActionGroup->add( Gtk::Action::create( "TaskResume", Gtk::Stock::MEDIA_PLAY ), Gtk::AccelKey( "<control>X" ),
		sigc::mem_fun ( *this, &main_window::on_menu_task_resume ) );
	refActionGroup->add( Gtk::Action::create( "TaskPause", Gtk::Stock::MEDIA_PAUSE ), Gtk::AccelKey( "<control>C" ),
		sigc::mem_fun( *this, &main_window::on_menu_task_pause ) );
	refActionGroup->add(Gtk::Action::create( "TaskResumeAll", "Resume All" ), Gtk::AccelKey( "<control><alt>X" ),
		sigc::mem_fun( *this, &main_window::on_menu_task_resume_all ) );
	refActionGroup->add(Gtk::Action::create( "TaskPauseAll", "Pause All" ), Gtk::AccelKey( "<control><alt>C" ),
		sigc::mem_fun( *this, &main_window::on_menu_task_pause_all ) );
	refActionGroup->add(Gtk::Action::create( "TaskUp", Gtk::Stock::GO_UP ),
		sigc::mem_fun( *this, &main_window::on_menu_task_up ) );
	refActionGroup->add(Gtk::Action::create( "TaskDown", Gtk::Stock::GO_DOWN ),
		sigc::mem_fun( *this, &main_window::on_menu_task_down ) );
	refActionGroup->add(Gtk::Action::create( "TaskRemove", Gtk::Stock::REMOVE ),
		sigc::mem_fun( *this, &main_window::on_menu_task_remove ) );

		/* help menu */

	refActionGroup->add( Gtk::Action::create("HelpMenu", "Help" ) );
	refActionGroup->add( Gtk::Action::create("HelpAbout", Gtk::Stock::ABOUT ),
		sigc::mem_fun( *this, &main_window::on_menu_help_about ) );
		
	refUIManager = Gtk::UIManager::create();
	refUIManager->insert_action_group( refActionGroup );
	
	add_accel_group( refUIManager->get_accel_group() );
	
	Glib::ustring ui_info = 
		"<ui>"
		"  <menubar name='MenuBar'>"
		"    <menu action='FileMenu'>"
		"      <menuitem action='FileQuit'/>"
		"    </menu>"
		"    <menu action='ViewMenu'>"
		"      <menuitem action='ViewStatus'/>"
//		"      <separator/>"
//		"      <menuitem action='ViewPreferences'/>"
		"    </menu>"
		"    <menu action='TaskMenu'>"
		"      <menuitem action='TaskNew'/>"
		"      <menuitem action='TaskResume'/>"
		"      <menuitem action='TaskPause'/>"
		"      <separator/>"
		"      <menuitem action='TaskResumeAll'/>"
		"      <menuitem action='TaskPauseAll'/>"
		"      <separator/>"
		"      <menuitem action='TaskUp'/>"
		"      <menuitem action='TaskDown'/>"
		"      <separator/>"
		"      <menuitem action='TaskRemove'/>"
		"    </menu>"
		"    <menu action='HelpMenu'>"
		"      <menuitem action='HelpAbout'/>"
		"    </menu>"
		"  </menubar>"
		"  <toolbar  name='ToolBar'>"
		"    <toolitem action='TaskNew'/>"
		"      <separator/>"
		"    <toolitem action='TaskResume'/>"
		"    <toolitem action='TaskPause'/>"
		"      <separator/>"
		"    <toolitem action='TaskUp'/>"
		"    <toolitem action='TaskDown'/>"
		"      <separator/>"
		"    <toolitem action='TaskRemove'/>"
		"  </toolbar>"
		"</ui>";

#ifdef GLIBMM_EXCEPTIONS_ENABLED
	try
	{      
		refUIManager->add_ui_from_string( ui_info );
	}
	catch( const Glib::Error& ex )
	{
		Util::msg_err( "Error: building menus failed: " +  ex.what() );
	}
#else
	std::auto_ptr< Glib::Error > ex;
	refUIManager->add_ui_from_string( ui_info, ex );
	if( ex.get() )
	{ 
		Util::msg_err( "Error: building menus failed: " +  ex.what() );
	}
#endif /* GLIBMM_EXCEPTIONS_ENABLED */

	Gtk::Widget* pMenubar = refUIManager->get_widget("/MenuBar");
	if( pMenubar )
		mainBox.pack_start( *pMenubar, Gtk::PACK_SHRINK );

	Gtk::Widget* pToolbar = refUIManager->get_widget( "/ToolBar" ) ;
	if( pToolbar )
		mainBox.pack_start( *pToolbar, Gtk::PACK_SHRINK );
}

void main_window::build_left_tree ( void )
{
		/* add the TreeView, inside a ScrolledWindow, with the button underneath */

//	ScrolledWindow_L.add( TreeView_L );

		/* only show the scrollbars when they are necessary */

//	ScrolledWindow_L.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );

//	HPaned.pack1( ScrolledWindow_L, false, false );
	HPaned.pack1( TreeView_L, false, false );

		/* create the Tree model */

	refTreeModel_L = Gtk::TreeStore::create( tableModel_L );
	TreeView_L.set_model( refTreeModel_L );

		/* fill the TreeView's model */

	Gtk::TreeModel::Row row = *( refTreeModel_L->append() );
	row[tableModel_L.group] = "Leafget";

	Gtk::TreeModel::Row childrow = *( refTreeModel_L->append( row.children() ) );
	childrow[tableModel_L.group] = _("Downloading");

	childrow = *( refTreeModel_L->append( row.children() ) );
	childrow[tableModel_L.group] = _("Completed");

	Gtk::TreeModel::Row completed_childrow = *( refTreeModel_L->append( childrow.children() ) );
	completed_childrow[tableModel_L.group] = _("Music");
	completed_childrow = *( refTreeModel_L->append( childrow.children() ) );
	completed_childrow[tableModel_L.group] = _("Movie");
	completed_childrow = *( refTreeModel_L->append( childrow.children() ) );
	completed_childrow[tableModel_L.group] = _("ISO");
	completed_childrow = *( refTreeModel_L->append( childrow.children() ) );
	completed_childrow[tableModel_L.group] = _("Software");

	childrow = *( refTreeModel_L->append( row.children() ) );
	childrow[tableModel_L.group] = _("Trash");

		/* add the TreeView's view columns */

	TreeView_L.append_column("", tableModel_L.group);
	
	TreeView_L.expand_all();
//	TreeView_L.set_size_request( 160, 150 );

		/* select running row */

	Gtk::TreeModel::Path path( "0:0" );
	TreeView_L.set_cursor( path );

		/* create the Select Tree */

	refTreeSelection_L = TreeView_L.get_selection();
	refTreeSelection_L->set_mode( Gtk::SELECTION_SINGLE );

		/* connect signal */

	TreeView_L.signal_cursor_changed().connect( sigc::mem_fun( *this, &main_window::on_treeview_cursor_changed ) );
}

void main_window::build_right_list ( void )
{
		/* add the TreeView, inside a ScrolledWindow, with the button underneath */

	ScrolledWindow_R1.add( TreeView_R1 );

		/* only show the scrollbars when they are necessary */

	ScrolledWindow_R1.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );

	VPanedR.pack1( ScrolledWindow_R1, false, false );
	
		/* add the TreeView's view columns */

	TreeView_R1.append_column( _("ID"), Columns_R1.id );
	TreeView_R1.append_column( _("File Name"), Columns_R1.name );
	TreeView_R1.append_column( _("Status"), Columns_R1.status );
	TreeView_R1.append_column( _("Size"), Columns_R1.size );
	TreeView_R1.append_column( _("Completed"), Columns_R1.completed );

		/* display a progress bar instead of a decimal number */

	Gtk::CellRendererProgress* cell = new Gtk::CellRendererProgress;
	int column_num = TreeView_R1.append_column( _("Progress"), *cell );
	Gtk::TreeViewColumn* pColumn = TreeView_R1.get_column( column_num - 1 );
	if( pColumn )
	{
#ifdef GLIBMM_PROPERTIES_ENABLED
		pColumn->add_attribute( cell->property_value(), Columns_R1.percentage );
#else
		pColumn->add_attribute( *cell, _("value"), Columns_R1.percentage );
#endif /* GLIBMM_PROPERTIES_ENABLED */
	}

	TreeView_R1.append_column( _("Speed"), Columns_R1.speed );
	TreeView_R1.append_column( _("Time Left"), Columns_R1.time );
	column_num = TreeView_R1.append_column( _("URL"), Columns_R1.url );

	for( int i = 0; i < column_num; i++ )
	{
		Gtk::TreeView::Column* pColumn = TreeView_R1.get_column( i );
		pColumn->set_reorderable();
		pColumn->set_resizable();
		pColumn->set_clickable();
		pColumn->set_sizing( Gtk::TREE_VIEW_COLUMN_AUTOSIZE );

		switch( i )
		{
				/* id */
			case 0:
				pColumn->set_min_width( 30 );
				pColumn->set_sort_order( Gtk::SORT_ASCENDING );
				break;
				/* name */
			case 1:
				pColumn->set_min_width( 230 );
				break;
				/* status */
			case 2:
				pColumn->set_min_width( 90 );
				break;
				/* size */
			case 3:
				pColumn->set_min_width( 90 );
				break;
				/* completed */
			case 4:
				pColumn->set_min_width( 90 );
				break;
				/* percentage */
			case 5:
				pColumn->set_min_width( 90 );
				break;
				/* speed */
			case 6:
				pColumn->set_min_width( 70 );
				break;
				/* time */
			case 7:
				pColumn->set_min_width( 70 );
				break;
				/* url */
			case 8:
				pColumn->set_min_width( 300 );
				break;
			default:
				break;
		}
	}

		/* create the tree model */

	refTreeModel_R1 = Gtk::ListStore::create( Columns_R1 );
	TreeView_R1.set_model( refTreeModel_R1 );
	TreeView_R1.set_size_request( 123, 150 );
	
		/* create the select tree */

	refTreeSelection_R1 = TreeView_R1.get_selection();
	refTreeSelection_R1->set_mode( Gtk::SELECTION_SINGLE );
}

void main_window::build_status_bar ( void )
{
	statusBar.pack_start( speedStatus, Gtk::PACK_SHRINK, 0 );

	speedStatus.set_label( _("Speed: 0 KB/s") );
}

void main_window::build_status_icon ( void )
{
	status_icon = Gtk::StatusIcon::create( refPixbuf_winIcon );
	status_icon->set_tooltip(" leafget " );

	status_icon->signal_activate().connect( sigc::mem_fun( *this, &main_window::on_status_icon_activate ) );
}

void main_window::build_right_msg_window( void )
{

}

	/* load functions */

void main_window::load_config (void)
{
	if( access( ( homePath + CONFIG_FILE_NAME ).c_str(), R_OK ) != -1 )
	{
		std::ifstream inFile ( ( homePath + CONFIG_FILE_NAME ).c_str(), std::ios::binary );
		bool tab = true;
		while( inFile && !inFile.eof() )
		{
			std::string line;
			getline(inFile, line);
			unsigned int posA;
			if( tab && line.find( "[preferences]" ) != std::string::npos )
				tab = false;
			
			else if( ! tab )
			{
				if( ( posA = line.find( "default_path=" ) ) != std::string::npos )
				{
					posA += 13;
					config.defaultPath = line.substr(posA, line.length());
				}
				else if( (posA = line.find( "tasks_limit=" ) ) != std::string::npos )
				{
					posA += 12;
					config.tasksLimit = atoi( ( line.substr( posA, line.length() ) ).c_str() );
				}
				else if( ( posA = line.find( "speed_limit=" ) ) != std::string::npos )
				{
					posA += 12;
					config.speedLimit = atoi( ( line.substr( posA, line.length() ) ).c_str() );
				}
				else if( ( posA = line.find( "default_pass=" ) ) != std::string::npos )
				{
					posA += 13;
					config.defaultPass = line.substr(posA, line.length());
				}
				else if( ( posA = line.find( "start_now=" ) ) != std::string::npos )
				{
					posA += 10;
					config.startNow = atoi( ( line.substr( posA, line.length() ) ).c_str() );
					tab = true;
				}
			}
		}
		inFile.close();
	}
	else
	{
		mkdir(homePath.c_str(), S_IRWXU);
		config.defaultPath = homePath;
		config.tasksLimit  = 0;
		config.speedLimit  = 0;
		config.startNow    = true;
		config.defaultPass = PACKAGE_BUGREPORT;
	}
}

void main_window::load_history ( void )
{
	if( access( ( homePath + HISTORY_FILE_NAME ).c_str(), R_OK ) == -1 )
	{
		return;
	}

	std::ifstream inFile ( ( homePath + HISTORY_FILE_NAME ).c_str(), std::ios::binary );
	bool tab = true;
	Gtk::TreeModel::Row row;
	LEAF_TASK_DATA *download;

	while( inFile && ! inFile.eof() )
	{
		std::string line;
		getline( inFile, line );
		unsigned int posA;
		if( tab && line[0] == '[' )
		{
			Gtk::TreeModel::iterator iter = refTreeModel_R1->append();
			row = *( iter );
			download = new LEAF_TASK_DATA;
			tab = false;
		}
		else if( ! tab )
		{
			if( ( posA = line.find( "name=" ) ) != std::string::npos )
			{
				posA += 5;
				row[Columns_R1.name] = line.substr( posA, line.length() );
				download->name = line.substr( posA, line.length() );
			}
			else if( ( posA = line.find( "size=" ) ) != std::string::npos )
			{
				posA += 5;
				row[Columns_R1.size] = line.substr( posA, line.length() );
				download->size = atoi( ( line.substr( posA, line.length() ) ).c_str() );
			}
			else if( ( posA = line.find( "completed=" ) ) != std::string::npos )
			{
				posA += 10;
				row[Columns_R1.completed] = line.substr( posA, line.length() );
				download->completed = atoi( ( line.substr( posA, line.length() ) ).c_str() );
			}
			else if( ( posA = line.find( "url=" ) ) != std::string::npos )
			{
				posA += 4;
				row[Columns_R1.url] = line.substr( posA, line.length() );
				download->url = line.substr( posA, line.length() );
			}
			else if( ( posA = line.find( "user=" ) ) != std::string::npos )
			{
				posA += 5;
				download->user = line.substr( posA, line.length() );
			}
			else if( ( posA = line.find( "pass=" ) ) != std::string::npos )
			{
				posA += 5;
				download->pass = line.substr( posA, line.length() );
			}
			else if( ( posA = line.find( "path=" ) ) != std::string::npos )
			{
				posA += 5;
				download->t = TASK_PAUSED;
				download->id = downloadsStore.get_size();
				download->speed = 0;
				download->dir = line.substr( posA, line.length() );
				download->listPath = Util::itoa( downloadsStore.get_size() ) + ":0";

				row[Columns_R1.id]        = downloadsStore.get_size();				
				row[Columns_R1.status]    = "paused";

				download->percentage = 0;
				download->option = OPTION_NOT_ASKED;
				if( download->size > 0 )
				{
					download->percentage = ( ( ( double ) download->completed ) / download->size ) * 100;
					download->option = OPTION_RESUME;
				}					

				if( download->percentage >= 100 )
					download->percentage = 100;
				row[Columns_R1.percentage] = download->percentage;

				row[Columns_R1.speed] = "";
				row[Columns_R1.time]  = "";

				downloadsStore.push_back( download );
				tab = true;
			}
		}
	}
	inFile.close();
}

	
	/* save functions */

void main_window::save_config ( void )
{
	if( access( homePath.c_str(), W_OK ) == -1 )
	{
		if( mkdir( homePath.c_str(), O_CREAT ) == -1 )
		{
			Util::msg_err( "Error: could not access config directory." );
			return;
		}
		else
			chmod( homePath.c_str(), S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH );
	}

	std::ofstream outFile ( ( homePath + CONFIG_FILE_NAME ).c_str(), std::ios::trunc | std::ios::binary );
	if( outFile )
	{
		outFile << "[preferences]" << std::endl;
		outFile << "default_path=" << config.defaultPath << std::endl;
		outFile << "tasks_limit="  << config.tasksLimit  << std::endl;
		outFile << "speed_limit="  << config.speedLimit  << std::endl;
		outFile << "default_pass=" << config.defaultPass << std::endl;
		outFile << "start_now="    << config.startNow    << std::endl;
	}
	outFile.close();
}

void main_window::save_history ( void )
{
	if( access( homePath.c_str(), W_OK ) == -1 )
	{
		if( mkdir( homePath.c_str(), O_CREAT ) == -1 )
		{
			Util::msg_err( "Error: could not access config directory." );
			return;
		}
		else
			chmod( homePath.c_str(), S_IWUSR | S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH );
	}

	std::ofstream outFile ( ( homePath + HISTORY_FILE_NAME ).c_str(), std::ios::trunc | std::ios::binary );

	struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = downloadsStore.get_first();
	for( int i = 0; temp; i++, temp = temp->next )
	{
		LEAF_TASK_DATA *download = temp->data;
		outFile << "[" << i << "]" << std::endl;
		outFile << "name="         << download->name      << std::endl;
		outFile << "size="         << download->size      << std::endl;
		outFile << "completed="    << download->completed << std::endl;
		outFile << "url="          << download->url       << std::endl;
		outFile << "user="         << download->user      << std::endl;
		outFile << "pass="         << download->pass      << std::endl;
		outFile << "path="         << download->dir       << std::endl << std::endl;
	}
	outFile.close();
}


	/* open cmd link */

void main_window::download_link ( const std::string &new_link )
{
	link = new_link;
	is_cmd = true;
	on_menu_task_new();
}

bool main_window::on_cmd_link ( void )
{
	int first = 1;
	bool url = false;
	cmd_connect.disconnect();

	if( argv[first] )
	{
		if( strcmp( argv[first], "--default" ) == 0 || strcmp( argv[first], "-d" ) == 0 )
		{
			first = 2;
			is_default = true;
		}
	}
	for( int i = first; argv[i]; i++ )
	{
		if( url )
		{
			download_link( argv[i] );
			url = false;
		}
		else if( strcmp( argv[i], "--url" ) == 0 || strcmp( argv[i], "-u" ) == 0 )
		{
			url = true;
			continue;
		}
	}
	if( url )
		return false;
	is_default = false;
	return true;
}


	/* set functions */

const bool main_window::set_default ( const bool &new_is_default )
{
	is_default = new_is_default;
	return true;
}


	/* menubar events */

void main_window::on_menu_file_quit ( void )
{
	hide();
}

void main_window::on_menu_view_status ( void )
{
	if( refStatusToggle->get_active() )
	{
		if( statusBar.get_parent() == NULL )
			mainBox.pack_start( statusBar, Gtk::PACK_SHRINK, 0 );
	}
	else
	{
		if( statusBar.get_parent() != NULL )
			mainBox.remove( statusBar );
	}
}

void main_window::on_menu_view_preferences ( void )
{
/*	Preferences *preferences = new Preferences( *this, config );
	if( preferences->run() == 1 )
	{
		std::string defaultPath = preferences->get_dir();
		config.tasksLimit  = preferences->get_tasksLimit();
		config.speedLimit  = preferences->get_speedLimit();
		config.defaultPass = preferences->get_pass();
		config.startNow    = preferences->get_start();

		if( config.speedLimit != 0 )
		{
			for ( int i = 0; i < MAX_TASKS; i++ )
			{
				if ( thread[i] && thread[i]->isRunning() )
					thread[i]->set_speedLimit( config.speedLimit / threadCount );
			}
		}
		if( ( access( defaultPath.c_str(), R_OK ) ) == -1 )
		{
			std::string title = "Directory Error";
			std::string temp_msg   = "Directory does not exist,\n"
								"would like to create?";

			Msg *msg = new Msg( *this, title, temp_msg, true );
			int awser = msg->run_msg();
			delete msg;

			if( awser )
			{
				if( mkdir( defaultPath.c_str(), 0766 ) == 0 )
				{
					config.defaultPath = defaultPath;

					Util::msg_out( "Preferences: directory created." );
				}
			}
		}
		else
		{
			DIR *dir_ptr = opendir ( defaultPath.c_str() );
			if( dir_ptr )
			{
				( void ) closedir ( dir_ptr );
				config.defaultPath = defaultPath;
			}
			else
			{
				std::string title = "Directory Error";
				std::string temp_msg   = "Could not change\n"
									"directory.";
				Msg *msg = new Msg( *this, title, temp_msg, false );
				msg->run_msg();
				delete msg;
			}
		}
		save_config();
	}
	delete preferences;
*/
}

void main_window::on_menu_task_new ( void )
{
	New *newtask = new New( *this, config );

	if( is_cmd )
	{
		newtask->set_url( link );
		is_cmd = false;
	}

	if( is_default || newtask->run() == 1 )
	{
		std::string dir = config.defaultPath;
		bool startNow = newtask->get_start();

		if( ( access( ( newtask->get_dir() ).c_str(), R_OK ) ) == -1 )
		{
			std::string title = "Directory Error";
			std::string temp_msg   = "Directory does not exist,\n"
								"would like to create?";

			Msg *msg = new Msg( *this, title, temp_msg, true );
			int awser = msg->run_msg();
			delete msg;

			if( awser )
			{
				if( mkdir( ( newtask->get_dir() ).c_str(), 0766 ) == 0 )
				{
					dir= newtask->get_dir();
					Util::msg_out( "New Task: directory created." );
				}
			}
		}
		else
		{
			DIR *dir_ptr = opendir ( ( newtask->get_dir() ).c_str() );
			if( dir_ptr )
			{
				( void ) closedir ( dir_ptr );
				dir = newtask->get_dir();
			}
			else
			{
				std::string title = "Directory Error";
				std::string temp_msg   = "Could not change\n"
									"directory.";
				Msg *msg = new Msg( *this, title, temp_msg, false );
				msg->run_msg();
				delete msg;
			}
		}

		LEAF_TASK_DATA *download = new LEAF_TASK_DATA;
		download->t          = TASK_PAUSED;
		download->option     = OPTION_NOT_ASKED;
		download->id         = downloadsStore.get_size();
		download->name       = newtask->get_name();
		download->size       = 0;
		download->completed  = 0;
		download->percentage = 0;
		download->speed      = 0;
		download->time       = "";
		download->url        = newtask->get_url();
		download->user       = newtask->get_user();
		download->pass       = newtask->get_pass();
		download->dir        = dir;
		download->listPath   = Util::itoa( downloadsStore.get_size() ) + ":0";

		if( listGroup == RUNNING_GROUP )
		{
			Gtk::TreeModel::Row row              = *( refTreeModel_R1->append() );
			row[Columns_R1.id]         = downloadsStore.get_size();
			row[Columns_R1.name]       = download->name;
			row[Columns_R1.status]     = "paused";
			row[Columns_R1.size]       = "";
			row[Columns_R1.completed]  = "";
			row[Columns_R1.percentage] = 0;
			row[Columns_R1.speed]      = "";
			row[Columns_R1.time]       = "";
			row[Columns_R1.url]        = download->url;
		}

		downloadsStore.push_back( download );

		if( startNow )
			start( download );
		else
			save_history();
	}
	delete newtask;
}

void main_window::on_menu_task_resume ( void )
{
	Glib::RefPtr< Gtk::TreeModel > refTreeMode = TreeView_R1.get_model();
			
	if( listGroup == RUNNING_GROUP )
	{
		Gtk::TreeModel::iterator iter = refTreeSelection_R1->get_selected();
		if( iter )
		{
			Gtk::TreeModel::Row row = *iter;
			LEAF_TASK_DATA *download = downloadsStore.get_data( row[Columns_R1.id] );

			if( download->t == TASK_PAUSED )
				start( download );
		}
	}
}

void main_window::on_menu_task_pause ( void )
{
	Glib::RefPtr< Gtk::TreeModel > refTreeMode = TreeView_R1.get_model();
			
	if( listGroup == RUNNING_GROUP )
	{
		bool change = false;
		Gtk::TreeModel::iterator iter = refTreeSelection_R1->get_selected();
		if( iter )
		{
			Gtk::TreeModel::Row row = *iter;
			LEAF_TASK_DATA *download = downloadsStore.get_data( row[Columns_R1.id] );

				/* try to pause a enqueued item */
			if( download->t == TASK_ENQUEUED )
			{
				struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = queueStore.get_first();
				for( int i = 0; temp; i++, temp = temp->next )
				{
					LEAF_TASK_DATA *download = temp->data;
					if( download->id  == download->id )
					{
						download->t = TASK_PAUSED;
						row[Columns_R1.status] = "paused";
						queueStore.erase( i );
						if( ! change )
							change = true;
						break;
					}
				}
			}
				/* try to pause a running item */
			else if( download->t != TASK_PAUSED )
			{
				int t = download->t;
				download->t = TASK_PAUSED;

				thread[t]->set_threadID( MAX_TASKS );
				thread[t]->stop();

				download->completed = thread[t]->get_comSize();

				if( ! change )
					change = true;
			}
			if( change )
				save_history();
		}
	}
}

void main_window::on_menu_task_resume_all ( void )
{
	struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = downloadsStore.get_first();
	while( temp )
	{
		LEAF_TASK_DATA *download = temp->data;
		temp = temp->next;

		if( download->t == TASK_PAUSED )
			start( download );
	}
}

void main_window::on_menu_task_pause_all ( void )
{
	if( threadCount == 0 )
		return;
	bool change = false;

		/* try to pause a enqueued item */

	struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = queueStore.get_first();
	for( int i = 0; temp; i++, temp = temp->next )
	{
		LEAF_TASK_DATA *download = temp->data;
		download->t = TASK_PAUSED;

		Gtk::TreeModel::Path path ( download->listPath );
		Gtk::TreeModel::iterator iter = refTreeModel_R1->get_iter( path );
		Gtk::TreeModel::Row row = *iter;

		row[Columns_R1.status] = "paused";

		if( ! change )
			change = true;
	}
	if( ! queueStore.clear() )
		Util::msg_err( "Error: could not clear task queue." );

		/* try to pause a running item */

	temp = downloadsStore.get_first();
	while( temp )
	{
		LEAF_TASK_DATA *download = temp->data;
		temp = temp->next;
		if( download->t != TASK_PAUSED && download->t != TASK_ENQUEUED )
		{
			int t = download->t;
			download->t = TASK_PAUSED;

			thread[t]->set_threadID( MAX_TASKS );
			thread[t]->stop();

			download->completed = thread[t]->get_comSize();

			if( ! change )
				change = true;
		}
	}
	if( change )
		save_history();
}

void main_window::on_menu_task_up ( void )
{
	Glib::RefPtr<Gtk::TreeModel> refTreeMode = TreeView_R1.get_model();
			
	if( listGroup == RUNNING_GROUP )
	{
		Gtk::TreeModel::iterator iter1 = refTreeSelection_R1->get_selected();
		if( iter1 )
		{
			Gtk::TreeModel::Row row1 = *iter1;
			int id = row1[Columns_R1.id];
			Gtk::TreeModel::iterator iter2 = iter1;
			iter2--;
			if( iter2 && id > 0 )
			{
				Gtk::TreeModel::Row row2 = *iter2;

				LEAF_TASK_DATA *download1 = downloadsStore.get_data( id );
				LEAF_TASK_DATA *download2 = downloadsStore.get_data( row2[Columns_R1.id] );

				download1->id = download2->id;
				download2->id = id;

				if( download1->t != TASK_PAUSED && download1->t != TASK_ENQUEUED )
					thread[download1->t]->set_id( download1->id );
				if( download2->t != TASK_PAUSED && download2->t != TASK_ENQUEUED )
					thread[download2->t]->set_id( download2->id );

				std::string pathString = download1->listPath;
				download1->listPath = download2->listPath;
				download2->listPath = pathString;

				downloadsStore.swap( download1->id, download2->id );

					/* change postions */

				refTreeModel_R1->iter_swap( iter1, iter2 );

					/* change id */

				row1[Columns_R1.id] = download1->id;
				row2[Columns_R1.id] = download2->id;

					/* swap status: enqueued <-> running */
				if( download1->t == TASK_ENQUEUED && download2->t != TASK_PAUSED && download2->t != TASK_ENQUEUED )
				{
						/* insert the running item after the first enqueued item, so as to be executed imidiately */
					queueStore.insert( 1, download2 );

					int t = download2->t;
					download2->t = TASK_ENQUEUED;

					thread[t]->set_threadID( MAX_TASKS );
					thread[t]->stop();

					download2->completed = thread[t]->get_comSize();
				}
				save_history();
			}
		}
	}
}

void main_window::on_menu_task_down ( void )
{
	Glib::RefPtr<Gtk::TreeModel> refTreeMode = TreeView_R1.get_model();
			
	if( listGroup == RUNNING_GROUP )
	{
		Gtk::TreeModel::iterator iter1 = refTreeSelection_R1->get_selected();
		if( iter1 )
		{
			Gtk::TreeModel::Row row1 = *iter1;
			int id = row1[Columns_R1.id];
			Gtk::TreeModel::iterator iter2 = iter1;
			iter2++;
			if( iter2 )
			{
				Gtk::TreeModel::Row row2 = *iter2;

				LEAF_TASK_DATA *download1 = downloadsStore.get_data( id );
				LEAF_TASK_DATA *download2 = downloadsStore.get_data( row2[Columns_R1.id] );

				download1->id = download2->id;
				download2->id = id;

				if( download1->t != TASK_PAUSED && download1->t != TASK_ENQUEUED )
					thread[download1->t]->set_id( download1->id );
				if( download2->t != TASK_PAUSED && download2->t != TASK_ENQUEUED )
					thread[download2->t]->set_id( download2->id );

				std::string pathString = download1->listPath;
				download1->listPath = download2->listPath;
				download2->listPath = pathString;

				downloadsStore.swap( download1->id, download2->id );

					/* change postions */

				refTreeModel_R1->iter_swap( iter1, iter2 );

					/* change id */

				row1[Columns_R1.id] = download1->id;
				row2[Columns_R1.id] = download2->id;


					/* swap status: running <-> enqueued */
				if( download1->t != TASK_PAUSED && download1->t != TASK_ENQUEUED && download2->t == TASK_ENQUEUED )
				{
						/* insert the running item after the first enqueued item, so as to be executed imidiately */
					queueStore.insert( 1, download1 );

					int t = download1->t;
					download1->t = TASK_ENQUEUED;

					thread[t]->set_threadID( MAX_TASKS );
					thread[t]->stop();

					download1->completed = thread[t]->get_comSize();
				}
				save_history();
			}
		}
	}
}

void main_window::on_menu_task_remove ( void )
{
	Gtk::TreeModel::iterator iter = refTreeSelection_R1->get_selected();
	if( ! iter )
		return;
	Gtk::TreeModel::Row row = *iter;
	int id = row[Columns_R1.id];

	Glib::RefPtr<Gtk::TreeModel> refTreeMode = TreeView_R1.get_model();
	if( listGroup == RUNNING_GROUP )
	{
		LEAF_TASK_DATA *download = downloadsStore.get_data( id );

		if( download->t != TASK_PAUSED )
		{
			std::string title = _("Remove Alert");
			std::string temp_msg = _("You must stop the download\n"
						    	  "before remove it");
			Msg *msg = new Msg( *this, title, temp_msg, false );
			msg->run_msg();
			delete msg;
		}
		else
		{
			refTreeModel_R1->erase( iter );
			refresh_downloads( id );
			downloadsStore.erase( id );
			delete download;
			save_history();
		}
	}
	else if( listGroup == COMPLETED_GROUP )
	{
		refTreeModel_R1->erase( iter );

		std::string listPath;
		struct LEAF_TASK_STORE < LEAF_COMPLETED_DATA > *temp = completedsStore.get_first();
		for( int i = 0; temp; i++, temp = temp->next )
		{
			LEAF_COMPLETED_DATA *completed = temp->data;
			if( i == id )
				listPath = completed->listPath;
			else if( i > id )
			{
				std::string temp = completed->listPath;
				completed->listPath = listPath;
				listPath = temp;
			}
		}
		completedsStore.erase( id );
		update_list = true;
	}
	else if( listGroup == TRASH_GROUP )
	{
		refTreeModel_R1->erase( iter );

		std::string listPath;
		struct LEAF_TASK_STORE < LEAF_TRASH_DATA > *temp = failedsStore.get_first();
		for( int i = 0; temp; i++, temp = temp->next )
		{
			LEAF_TRASH_DATA *failed = temp->data;
			if( i == id )
				listPath = failed->listPath;
			else if( i > id )
			{
				std::string temp = failed->listPath;
				failed->listPath = listPath;
				listPath = temp;
			}
		}
		failedsStore.erase( id );
		update_list = true;
	}
}

void main_window::on_menu_help_about ( void )
{
//	Gtk::AboutDialog about;
	
//	GdkPixbuf *pixbuf = NULL;
//	gchar *logo_file;

//	logo_file=g_strdup_printf("%s/%s","../data","newdownloading.png");
//	logo_file=g_strdup_printf("../data/shamrock.png");
//	pixbuf = gdk_pixbuf_new_from_file (logo_file, NULL);
//	g_free (logo_file);
	GdkPixbuf* pixbuf = NULL;
	pixbuf = gdk_pixbuf_new_from_xpm_data ( shamrock );
	
	const gchar * const authors[] = {
                "XinliGG  xinliGG@gmail.com",
                NULL
        };

/*        const gchar * const documenters[] = {
                "xinliGG",
                NULL
        };

        const gchar * const artists[] = {
                "xinliGG",
                NULL
        };
*/        gtk_show_about_dialog (
                NULL,
                "name",                 "Leafget",
                "comments",             _("Download Manager"),
                "version",              LEAFGET_VERSION,
                "copyright",            _("Copyright \xc2\xa9 2006-2008 xinliGG\n"),
//                "logo-icon-name",       "utilities-system-monitor",
                "logo",       pixbuf,
                "authors",              authors,
//                "artists",              artists,
//                "documenters",          documenters,
                "translator-credits",   "translator-credits",
                "license",              "GPL 2+",
                "wrap-license",         TRUE,
                NULL
                );


}

	/* treeview events */

void main_window::on_treeview_cursor_changed ( void )
{
	Gtk::TreeModel::iterator iter = refTreeSelection_L->get_selected();
	if(iter)
	{
		Gtk::TreeModel::Row row = *iter;
		Glib::ustring tabName = row[tableModel_L.group];
		if( tabName.compare( _("Running") ) == 0 )
		{
			listGroup = RUNNING_GROUP;
			update_list = true;
		}
		else if ( tabName.compare( _("Completed") ) == 0 )
		{
			listGroup = COMPLETED_GROUP;
			update_list = true;
		}
		else if ( tabName.compare( _("Trash") ) == 0 )
		{
			listGroup = TRASH_GROUP;
			update_list = true;
		}
	}
}


	/* status icon events */

void main_window::on_status_icon_activate ( void )
{
	if( is_visible() )
	{
//		Util::msg_out( "Window on." );
	}
	else
	{
//		Util::msg_out( "Window off." );
	}
}


	/* list timer event */

bool main_window::on_list_timer ( void )
{
	if( listGroup == RUNNING_GROUP )
	{
		if( update_list )
		{
			refTreeModel_R1->clear();
			struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = downloadsStore.get_first();

			while( temp )
			{
				LEAF_TASK_DATA *download = temp->data;
				temp = temp->next;

				Gtk::TreeModel::Row row              = *( refTreeModel_R1->append() );
				row[Columns_R1.id]         = download->id;
				row[Columns_R1.name]       = download->name;
				if( download->t == TASK_PAUSED )
					row[Columns_R1.status] = "paused";
				else if ( download->t == TASK_ENQUEUED )
					row[Columns_R1.status] = "enqueued";
				else
					row[Columns_R1.status] = "running";
				row[Columns_R1.size]       = Util::converter_human_size( download->size );
				row[Columns_R1.completed]  = Util::converter_human_size( download->completed );
				row[Columns_R1.percentage] = download->percentage;
				if( download->t == TASK_PAUSED || download->t == TASK_ENQUEUED )
				{
					row[Columns_R1.speed]  = "";
					row[Columns_R1.time]   = "";
				}
				else
				{
					row[Columns_R1.speed]  = Util::get_speed( download->speed );
					row[Columns_R1.time]   = download->time;
				}
				row[Columns_R1.url]        = download->url;				
			}
			update_list = false;
		}
		else
		{
			for( int i = 0; i < MAX_TASKS; i++ )
			{
				if( thread[i] && thread[i]->isRunning() && listGroup == RUNNING_GROUP )
				{
					Gtk::TreeModel::Path path ( thread[i]->get_listPath() );
					Gtk::TreeModel::iterator iter = refTreeModel_R1->get_iter( path );
					Gtk::TreeModel::Row row       = *iter;

					row[Columns_R1.status]     = "running";
					row[Columns_R1.size]       = Util::converter_human_size( thread[i]->get_totalSize() );
					row[Columns_R1.completed]  = Util::converter_human_size( thread[i]->get_comSize() );
					row[Columns_R1.percentage] = thread[i]->get_percentage();
					row[Columns_R1.speed]      = Util::get_speed( thread[i]->get_speed() );
					row[Columns_R1.time]       = thread[i]->get_time();
				}
			}
		}
	}
	else if( listGroup == COMPLETED_GROUP && update_list )
	{
		refTreeModel_R1->clear();
		struct LEAF_TASK_STORE < LEAF_COMPLETED_DATA > *temp = completedsStore.get_first();
		for( int i = 0; temp; i++, temp = temp->next )
		{
			LEAF_COMPLETED_DATA *completed = temp->data;

			Gtk::TreeModel::Row row              = *( refTreeModel_R1->append() );
			row[Columns_R1.id]         = i;
			row[Columns_R1.name]       = completed->name;
			row[Columns_R1.status]     = "completed";
			row[Columns_R1.size]       = completed->size;
			row[Columns_R1.completed]  = completed->size;
			row[Columns_R1.percentage] = 100;
			row[Columns_R1.speed]      = "";
			row[Columns_R1.time]       = "";
			row[Columns_R1.url]        = completed->url;
		}
		update_list = false;
	}
	else if( listGroup == TRASH_GROUP && update_list )
	{
		refTreeModel_R1->clear();
		struct LEAF_TASK_STORE < LEAF_TRASH_DATA > *temp = failedsStore.get_first();
		for( int i = 0; temp; i++, temp = temp->next )
		{
			LEAF_TRASH_DATA *failed = temp->data;

			Gtk::TreeModel::Row row              = *( refTreeModel_R1->append() );
			row[Columns_R1.id]         = i;
			row[Columns_R1.name]       = failed->name;
			row[Columns_R1.status]     = "failed";
			row[Columns_R1.size]       = failed->size;
			row[Columns_R1.completed]  = failed->completed;
			row[Columns_R1.percentage] = failed->percentage;
			row[Columns_R1.speed]      = "";
			row[Columns_R1.time]       = "";
			row[Columns_R1.url]        = failed->url;
		}
		update_list = false;
	}

		/* refresh statusbar */

	int totalSpeed = 0;
	for( int i = 0; i < MAX_TASKS; i++ )
	{
		if( thread[i] && thread[i]->isRunning() )
			totalSpeed += thread[i]->get_speed();
	}

	speedStatus.set_label( "Speed: " + Util::itoa( totalSpeed ) + " KB/s" );

	return true;
}


	/* file event: paused | completed | failed */

void main_window::on_download_paused ( Net *net )
{
	Util::msg_out( "PAUSED 1-3" );

	threadCount--;
	update_list = true;

		/* running a enqueued item */
	if( queueStore.get_size() > 0 )
	{
		Util::msg_out( "PAUSED 2-3" );

		LEAF_TASK_DATA *download = queueStore.pop_front();
		start( download );
	}
	Util::msg_out( "PAUSED 3-3" );
}

void main_window::on_download_completed ( Net *net )
{
	Util::msg_out( "COMPLETED 1-4" );

	LEAF_COMPLETED_DATA *completed = new LEAF_COMPLETED_DATA;

	Glib::Mutex mutex;
	{
		Glib::Mutex::Lock lock ( mutex );

		completed->name     = net->get_name();
		completed->size     = Util::converter_human_size( net->get_totalSize() );
		completed->url      = net->get_url();
		completed->listPath = Util::itoa( completedsStore.get_size() ) + ":0";
		completedsStore.push_back( completed );

		refresh_downloads( net->get_id() );
		
		int id = net->get_id();
		LEAF_TASK_DATA *download = downloadsStore.get_data( id );
		delete download;
		downloadsStore.erase( id );

		net->set_threadID( MAX_TASKS );
		threadCount--;

		update_list = true;
	}
	save_history();

	Util::msg_out( "COMPLETED 2-4" );

		/* running a enqueued item */
	if( queueStore.get_size() > 0 )
	{
		Util::msg_out( "COMPLETED 3-4" );

		LEAF_TASK_DATA *download = queueStore.pop_front();
		start( download );
	}
	Util::msg_out( "COMPLETED 4-4" );
}

void main_window::on_download_failed ( Net *net )
{
	Util::msg_out( "FAILED 1-3" );

	LEAF_TRASH_DATA *failed = new LEAF_TRASH_DATA;

	Glib::Mutex mutex;
	{
		Glib::Mutex::Lock lock ( mutex );

		failed->name       = net->get_name();
		failed->size       = Util::converter_human_size( net->get_totalSize() );
		failed->completed  = Util::converter_human_size( net->get_comSize() );
		failed->percentage = net->get_percentage();
		failed->url        = net->get_url();
		failed->listPath   = Util::itoa( failedsStore.get_size() ) + ":0";
		failedsStore.push_back( failed );

		refresh_downloads( net->get_id() );

		int id = net->get_id();
		LEAF_TASK_DATA *download = downloadsStore.get_data( id );
		delete download;
		downloadsStore.erase( id );

		net->set_threadID( MAX_TASKS );
		threadCount--;

		update_list = true;
	}
	save_history();

	Util::msg_out( "FAILED 2-3" );

		/* running a enqueued item */
	if( queueStore.get_size() > 0 )
	{
		LEAF_TASK_DATA *download = queueStore.pop_front();
		start( download );
	}
	Util::msg_out( "FAILED 3-3" );
}


	/* actions functions */

void main_window::define_home ( void )
{
	char * home;
	home = getenv ("HOME");

	homePath = "";
	if( home )
	{
		homePath.append( home );
//		homePath.append( "/" );
		homePath.append( "/.leafget/" );
	}
	else
		homePath = "/tmp/";
}

void main_window::start ( LEAF_TASK_DATA *download )
{
	if( threadCount <= config.tasksLimit )
	{
		int t = MAX_TASKS;
		for( int i = 0; i < MAX_TASKS; i++ )
		{
			if( thread[i] == NULL )
			{
				t = i;
				break;
			}
			else if( thread[i]->get_threadID() == MAX_TASKS )
			{
				t = i;
				delete thread[i];
				thread[i] = NULL;
				break;
			}
		}
		if( t != MAX_TASKS )
		{
			Util::msg_out( "RUNNING" );

			Net *net = new Net( this, download );

			Glib::Mutex mutex;
			{
				Glib::Mutex::Lock lock ( mutex );
				if( ! net->create( download->url ) )
				{
					on_download_failed( net );
					return;
				}
				net->set_path( download->dir + "/" + download->name );

				download->t = t;
				thread[t] = net;
				thread[t]->set_threadID( t );
				thread[t]->set_speedLimit( config.speedLimit / ( threadCount + 1 ) );
				thread[t]->signal_paused().connect( sigc::mem_fun( *this, &main_window::on_download_paused ) );
				thread[t]->signal_completed().connect( sigc::mem_fun( *this, &main_window::on_download_completed ) );
				thread[t]->signal_failed().connect( sigc::mem_fun( *this, &main_window::on_download_failed ) );
				thread[t]->start();
				threadCount++;
			}
		}
		else
		{
			Util::msg_out( "ENQUEUED 1" );

			download->t = TASK_ENQUEUED;
			queueStore.push_back( download );
			update_list = true;
		}
	}
	else
	{
		Util::msg_out( "ENQUEUED 2" );

		download->t = TASK_ENQUEUED;
		queueStore.push_back( download );
		update_list = true;
	}
}

void main_window::refresh_downloads ( int id )
{
	std::string listPath;
	struct LEAF_TASK_STORE < LEAF_TASK_DATA > *temp = downloadsStore.get_first();
	for( int i = 0; temp; i++, temp = temp->next )
	{
		LEAF_TASK_DATA *downloads = temp->data;
		if( i == id )
			listPath = downloads->listPath;
		else if( i > id )
		{
			std::string temp = downloads->listPath;
			downloads->id = id;
			downloads->listPath = listPath;
			listPath = temp;
			id++;
		}
	}
}

void main_window::connect_list_timer ( void )
{
	if( ! list_timer.connected() )
		list_timer = Glib::signal_timeout().connect( sigc::mem_fun( *this, &main_window::on_list_timer ), LIST_TIMER );
}

void main_window::disconnect_list_timer ( void )
{
	if(list_timer.connected())
		list_timer.disconnect();
}



/* EOF */
